/*
 * @Description:
 * @Version: 1.0
 * @Autor: lzc
 * @Date: 2021-09-06 09:20:17
 * @LastEditors: lzc
 * @LastEditTime: 2021-09-15 16:42:34
 */

#include <rthw.h>
#include <stdint.h>
#include <rtthread.h>
#include "upacker.h"
#include "stdio.h"
#include "shell.h"
#include "stdlib.h"
#include "string.h"
#include "misc.h"
#include "m1130_uart.h"
#include "m1130_gpio.h"
#include "m1130_rcc.h"
#include "m1130_dma.h"
#include "m1130_adc.h"
#include "m1130_wdg.h"
#include "m1130_utility_usart.h"
#include "command_parse.h"

#define KEY_PIN             GPIO_Pin_23
#define LED_PIN             GPIO_Pin_20
#define LED_PORT            GPIO0
#define ADCx                ADC0
#define ADCx_IRQn           ADC0_IRQn
#define ADCx_IRQHandler     ADC0_IRQHandler
#define AHBCLK_BIT_ADCx     AHBCLK_BIT_ADC0
#define ADC_Channelx        ADC_CHANNEL0

#define ADC_TRAG_MODE       ADC_TrigEdge_Software
#define ADC_TRAG_SRC        ADC_Internal_TrigSrc_TIM16_CH1

#define TIMx                TIM16
#define AHBCLK_BIT_TIMx     AHBCLK_BIT_TIM16

#define ADC_Collect_Time        30


#define THREAD_PRIORITY         10
#define THREAD_STACK_SIZE       512
#define THREAD_TIMESLICE        10
#define COM_TYPE_HEX            2
#define COM_TYPE_STR            3

static rt_thread_t tid1  = RT_NULL;
static rt_thread_t tid2  = RT_NULL;
static char sys_FinSH_Status = 0;

extern upacker_inst msg_packer; 
extern UartRecvBufferStruct Uart1_Recv;
extern void uart_send( uint8_t *d, uint16_t size);
extern void handle_cb(uint16_t command, uint8_t *d, uint16_t size);
typedef struct
{
    uint32_t ADC_Result_Val;     // ADC转换结果
    uint8_t  ADC_Channel;        // ADC_Channel
    uint8_t  ADC_Collect_Status; // ADC 采集状态
    uint32_t ADC_Collect_Sum;    // ADC 数据总数
    uint8_t  ADC_Collect_Times;  // ADC 采集次数
} ADC_Status_t;

ADC_Status_t ADC_Status;

int startup_thread(void);
int back_FinSH(void);
int exit_FinSH(void);

void TIMx_Init(void)
{
    RCC_SetAHBCLK(1 << AHBCLK_BIT_TIMx, ENABLE);
    TIMx->ARR       = 10000;
    TIMx->CCR1      = 5000;
    TIMx->CCR4      = 5000;
    TIMx->CNT       = 0;
    TIMx->PSC       = 599;
    TIMx->CCMR1    |= 6 << 4;  //PWM1 mode
    TIMx->CCMR1    |= 6 << 12;
    TIMx->CCMR2    |= 6 << 4;  //PWM1 mode
    TIMx->CCMR2    |= 6 << 12;
    TIMx->CCER     |= TIM_CCER_CC1E;
    // TIMx->CCER     |= TIM_CCER_CC2E;
    // TIMx->CCER     |= TIM_CCER_CC3E;
    TIMx->CCER     |= TIM_CCER_CC4E;
    TIMx->BDTR      = (3 << 0) | TIM_BDTR_MOE;
    TIMx->CR1      |= TIM_CR1_CEN;
}

void Adc_Config(void)
{
    ADC_InitTypeDef ADC_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;


    ADC_InitStruct.ADC_Channel = ADC_Channelx;
    ADC_InitStruct.ADC_ClkDiv = 4;
    ADC_InitStruct.ADC_Exch_DisSampleNum = 0;
    ADC_InitStruct.ADC_First_DisSampleNum = 0;
    ADC_InitStruct.ADC_SampFrqSel = ADC_142K_SampFrq;                   //采样率
    ADC_InitStruct.ADC_SingleTrigConvMode = ADC_SingleTrigConv_Enable;  //单次触发
    ADC_InitStruct.ADC_TrigConvEdge = ADC_TRAG_MODE;                    //触发模式
    ADC_InitStruct.ADC_TrigConvSrcSel = ADC_TRAG_SRC;                   //触发源
    ADC_Init(ADCx, &ADC_InitStruct);
    ADC_ITConfig(ADCx, ENABLE);
    //ADC_SetAccumulate(ADCx, ADC_Channelx, 3);

    NVIC_InitStruct.NVIC_IRQChannel = ADCx_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
    NVIC_Init(&NVIC_InitStruct);

    ADC_Run(ADCx, ENABLE);
}


/**
  * @brief  清除
  * @note
  * @param  *d:
  * @param  size:
  * @retval None
  */
static void Clear_Uart(UartRecvBufferStruct *Uartx_recv)
{
    Uartx_recv->rxlen = 0;
    Uartx_recv->rx_flag = 0;
    Uartx_recv->rx_ptr = 0;
    memset(Uartx_recv->rx_buf, 0, UART_RX_BUFFER_SIZE);
}




/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main()
{
    GPIO_SetPinMux(LED_PORT, LED_PIN, GPIO_FUNCTION_0);
    GPIO_SetPinDir(LED_PORT, LED_PIN, GPIO_Mode_OUT);
    GPIO_ClearPin(LED_PORT, LED_PIN);
    while (1)
    {
        GPIO_SetPin(LED_PORT, LED_PIN);
        rt_thread_mdelay(500);
        GPIO_ClearPin(LED_PORT, LED_PIN);
        rt_thread_mdelay(500);
        // 检测FinSH的状态如果是回显则关闭回显
        if (finsh_get_echo() == 0x01)
        {
            finsh_set_echo(0);      // 关闭回显
            finsh_set_prompt("\0"); // 关闭MSH显示
        }
    }
}

/* ADC采集线程 入口函数 */
static void ADC_Sample_Thread_entry(void *parameter)
{
    Adc_Config();
    TIMx_Init();
    ADC_Status.ADC_Collect_Status   = 0;
    ADC_Status.ADC_Collect_Times    = 0;
    ADC_Status.ADC_Result_Val       = 0;
    ADC_Status.ADC_Collect_Sum      = 0;
    while (1)
    {
        if (ADC_TRAG_MODE == ADC_TrigEdge_Software)
        {
            ADC_StartSoftwareTrigConv(ADCx); /*software trigger test*/
            if (ADC_Status.ADC_Collect_Status == 1)
            {
                ADC_Status.ADC_Result_Val = ADC_Status.ADC_Collect_Sum / ADC_Status.ADC_Collect_Times;
                ADC_Status.ADC_Collect_Sum      = 0;
                ADC_Status.ADC_Collect_Times    = 0;
                ADC_Status.ADC_Collect_Status   = 0;// 处理完成
                // printf( "ADC Channel %d Result Val = %04d Voltage  = %.3fV ",
                //         ADC_Status.ADC_Channel, ADC_Status.ADC_Result_Val, (3.3 / 4096)* ADC_Status.ADC_Result_Val);
                // printf( "%.3f",  (3.3 / 4096)* ADC_Status.ADC_Result_Val);
                // printf("\r\n");
            }
        }
        rt_thread_mdelay(10);
    }
}
//使用串口16进制解析
static void upacker_thread_entry(void *parameter)
{
    rt_err_t result;
    rt_thread_t FinSH_Task;
    //init packer
    upacker_init(&msg_packer, handle_cb, uart_send);
    // 先退出FinSH模式
    FinSH_Task = rt_thread_find(FINSH_THREAD_NAME);
    rt_thread_suspend(FinSH_Task);
    sys_FinSH_Status = 0;
    while (1)
    {
        if (!sys_FinSH_Status) // 没有FinSH
        {
            /* 从消息队列中读取消息*/
            // 如果是16进制
            if (Uart1_Recv.rx_buf[0] == 0xA5 && Uart1_Recv.rx_buf[1] == 0x5A )
            {
                result = COM_TYPE_HEX;
            }
            // 如果是字符串
            else if (Uart1_Recv.rx_buf[0] != 0x00)
                result = COM_TYPE_STR;
            else
                result = RT_ERROR;

            // 16进制解析
            if (result == COM_TYPE_HEX)
            {
                //丢到packer解析，成功了调用callback
                upacker_unpack(&msg_packer, (uint8_t *)Uart1_Recv.rx_buf, Uart1_Recv.rxlen);
                Clear_Uart(&Uart1_Recv);
            }
            // 字符串解析
            else if (result == COM_TYPE_STR)
            {
                if (strcmp(Uart1_Recv.rx_buf, "back_FinSH\r\n") == 0)
                {
                    back_FinSH();
                    Clear_Uart(&Uart1_Recv);
                }
                else
                {
                    // TODO: 开始解析字符串
                    msg_parse((const char *)Uart1_Recv.rx_buf);
                    Clear_Uart(&Uart1_Recv);
                }
            }
        }
        rt_thread_mdelay(10);
    }
}



/**
 * @function: startup_thread
 * @brief: 启动线程
 * @param {*}
 * @return {*}
 * @author: lzc
 */
int startup_thread(void)
{
    /* 创建线程 1，名称是 thread1，入口是 thread1_entry*/
    tid1 = rt_thread_create("thread1",
                            ADC_Sample_Thread_entry, RT_NULL,
                            THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);
    /* 如果获得线程控制块，启动这个线程 */
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);

    /* 创建线程 2，名称是 thread2，入口是 thread1_entry*/
    tid2 = rt_thread_create("thread2",
                            upacker_thread_entry, RT_NULL,
                            THREAD_STACK_SIZE,
                            THREAD_PRIORITY, THREAD_TIMESLICE);
    /* 如果获得线程控制块，启动这个线程 */
    if (tid2 != RT_NULL)
        rt_thread_startup(tid2);
    return 0;
}
INIT_APP_EXPORT(startup_thread);

/**
 * @function: back_FinSH
 * @brief:
 * @param {*}
 * @return {*}
 * @author: lzc
 */
int back_FinSH(void)
{
    rt_thread_t FinSH_Task;
    FinSH_Task = rt_thread_find(FINSH_THREAD_NAME);
    sys_FinSH_Status = 1;
    rt_thread_resume(FinSH_Task); return 0;
}
MSH_CMD_EXPORT(back_FinSH, Back the FinSH Mode);

/**
 * @function: exit_FinSH
 * @brief:
 * @param {*}
 * @return {*}
 * @author: lzc
 */
int exit_FinSH(void)
{
    rt_thread_t FinSH_Task;
    FinSH_Task = rt_thread_find(FINSH_THREAD_NAME);
    sys_FinSH_Status = 0;
    rt_thread_suspend(FinSH_Task); return 0;
}
MSH_CMD_EXPORT(exit_FinSH, Exit the FinSH Mode);

/**
  * @brief  This function handles ADC Handler.
  * @param  None
  * @retval None
  */
uint32_t val = 0;
uint32_t flag_val = 0;
void ADCx_IRQHandler(void)
{
#if 1
    int i = 0;
    uint32_t adcon;
    /* enter interrupt */
    rt_interrupt_enter();
    /*get irq flag*/
    for (i = 0; i < 10; i++)
    {
        if (ADC_GetITStatus(ADCx, 1 << i))
        {
            /*get channel converted value*/
            adcon = ADC_GetConvValue(ADCx, 1 << i);
            // printf("ch %d = %04d ", i, adcon);
            if (ADC_Status.ADC_Collect_Status == 0)
            {
                ADC_Status.ADC_Channel = i;         // 转换通道赋值
                ADC_Status.ADC_Collect_Sum += adcon;// 数据累加
                ADC_Status.ADC_Collect_Status = 0;  // 状态赋值为采集中
                ADC_Status.ADC_Collect_Times ++;
            }
            if (ADC_Status.ADC_Collect_Times == ADC_Collect_Time
                    && ADC_Status.ADC_Collect_Status == 0)
            {
                ADC_Status.ADC_Collect_Status = 1; // 处理中
            }
        }
        /* clear it flag */
        ADC_ClearITFlag(ADCx, 1 << i);
    }
#else
    ADCx->CTRL1_CLR = 0x3FF;
#endif
    /* leave interrupt */
    rt_interrupt_leave();
}


